package com.gwlc.common.result;

import com.fasterxml.jackson.annotation.JsonValue;
import com.gwlc.common.exception.base.BaseException;
import lombok.Data;
import org.springframework.http.HttpStatus;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>lucky-com.gwlc.common-ResultGenerate</p>
 * <p>Description: 返回类型 </p>
 * <p>Copyright: Copyright (c) 2021</p>
 * <p>Company: hanchunit@163.com</p>
 *
 * @author hanchun
 * @version 1.0
 * @date
 */

@Data
public class Result<T> implements Serializable {

    private static final long serialVersionUID = 8140914548530887640L;
    private Integer status;

    private String msg = "调用成功";

    private Map<String, Object> meta = new HashMap<>();

    private T data;

    public Result() {

    }

    public Result(Integer status, String msg, T data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    public Result(Integer status, String msg) {
        this.status = status;
        this.msg = msg;
    }

    /**
     * 返回成功结果数据
     *
     * @param data 返回数据
     * @return 成功结果数据
     */
    public static <T> Result<T> ok(T data) {
        return buildOkResult(null, data);
    }

    /**
     * 创建成功结果
     *
     * @param msg  成功消息
     * @param data 返回数据
     * @return 结果数据
     */
    private static <T> Result<T> buildOkResult(String msg, T data) {
        Result<T> result = new Result<>();
        result.setMsg(msg);
        result.setData(data);
        result.setStatus(HttpStatus.OK.value());
        return result;
    }

    /**
     * 返回成功结果数据
     *
     * @param data 返回数据
     * @return 成功结果数据
     */
    public static <T> Result<T> ok(T data, Integer exist) {
        return buildOkResult(null, data);
    }

    /**
     * 返回失败结果数据
     *
     * @param msg  失败消息
     * @param data 返回数据
     * @return 失败结果数据
     */
    public static <T> Result<T> failed(String msg, T data) {
        return buildFailedResult(msg, data);
    }

    /**
     * 创建失败结果
     *
     * @param msg  失败消息
     * @param data 返回数据
     * @return 结果数据
     */
    private static <T> Result<T> buildFailedResult(String msg, T data) {
        Result<T> result = new Result<>();
        result.setStatus(HttpStatus.BAD_REQUEST.value());
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

    /**
     * 返回错误结果数据
     *
     * @param msg 错误消息
     * @return 错误结果数据
     */
    public static <T> Result<T> error(String msg) {
        return buildErrorResult(msg);
    }

    /**
     * 创建错误结果
     *
     * @param msg 错误消息
     * @return 结果数据
     */
    private static <T> Result<T> buildErrorResult(String msg) {
        Result<T> result = new Result<>();
        result.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        result.setMsg(msg);
        return result;
    }

    /**
     * 返回成功或失败的结果数据
     *
     * @param isOk 是否成功
     * @return 结果数据
     */
    public static <T> Result<T> okOrFailed(boolean isOk) {
        if (isOk) {
            return Result.ok();
        } else {
            return Result.failed();
        }
    }

    /**
     * 返回成功结果数据
     *
     * @return 成功结果数据
     */
    public static <T> Result<T> ok() {
        return buildOkResult(null, null);
    }

    /**
     * 返回失败结果数据
     *
     * @return 失败结果数据
     */
    public static <T> Result<T> failed() {
        return buildFailedResult(null, null);
    }

    /**
     * 返回成功或失败的结果数据
     *
     * @param isOk      是否成功
     * @param okMsg     成功消息
     * @param failedMsg 失败消息
     * @return 结果数据
     */
    public static <T> Result<T> okOrFailed(boolean isOk, String okMsg, String failedMsg) {
        if (isOk) {
            return Result.ok(okMsg);
        } else {
            return Result.failed(failedMsg);
        }
    }

    /**
     * 返回成功结果数据
     *
     * @param msg 消息提示
     * @return 成功结果数据
     */
    public static <T> Result<T> ok(String msg) {
        return buildOkResult(msg, null);
    }

    /**
     * 返回失败结果数据
     *
     * @param msg 失败消息
     * @return 失败结果数据
     */
    public static <T> Result<T> failed(String msg) {
        return buildFailedResult(msg, null);
    }

    /**
     * 返回成功或失败的结果数据
     *
     * @param isOk      是否成功
     * @param okMsg     成功消息
     * @param failedMsg 失败消息
     * @return 结果数据
     */
    public static <T> Result<T> okOrFailed(boolean isOk, String okMsg, String failedMsg, T date) {
        if (isOk) {
            return Result.ok(okMsg, date);
        } else {
            return Result.failed(failedMsg);
        }
    }

    /**
     * 返回成功结果数据
     *
     * @param msg  成功消息
     * @param data 返回数据
     * @return 成功结果数据
     */
    public static <T> Result<T> ok(String msg, T data) {
        return buildOkResult(msg, data);
    }

    public static <T> Result<T> result(Integer status, String msg, T data) {
        return new Result<>(status, msg, data);
    }

    public static <T> Result<T> exception(BaseException e) {

        if (e.getExist() == null) {
            return new Result<>(e.getStatus(), e.getMsg());

        }
        Result<T> result = new Result<>(e.getStatus(), e.getMsg());
        result.getMeta().put("exist", e.getExist());
        return result;
    }

    @JsonValue
    public Map<String, Object> toMap() {
        Map<String, Object> map = new HashMap<>();
        meta.put("msg", getMsg());
        meta.put("status", getStatus());
        map.put("meta", getMeta());
        map.put("data", getData());
        return map;

    }

}
